package com.itheima.prize.msg;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.prize.commons.config.RedisKeys;
import com.itheima.prize.commons.db.entity.*;
import com.itheima.prize.commons.db.service.*;
import com.itheima.prize.commons.utils.RedisUtil;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 活动信息预热，每隔1分钟执行一次
 * 查找未来1分钟内（含），要开始的活动
 */
@Component
public class GameTask {
    private final static Logger log = LoggerFactory.getLogger(GameTask.class);
    @Autowired
    private CardGameService gameService;
    @Autowired
    private CardGameProductService gameProductService;
    @Autowired
    private CardGameRulesService gameRulesService;
    @Autowired
    private GameLoadService gameLoadService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CardProductService cardProductService;

    @Scheduled(cron = "0 * * * * ?")
    public void execute() {
        System.out.printf("scheduled!"+new Date());
        //TODO
        //获取当前时间的calendar实例
        Calendar calendar = Calendar.getInstance();
        //消除毫秒部分
        calendar.set(Calendar.MILLISECOND,0);
        //获取不带毫秒的date对象
        Date now = calendar.getTime();
        //分布式锁，防止重复启动任务
        if(!redisUtil.setNx("game_task_"+now.getTime(),1,60L)){
            log.info("task started by another server!");
            return;
        }
        //1、查询数据库--（开始时间 > 当前时间）&& （开始时间 <= 当前时间+1分钟）的活动
        List<CardGame> cardGameList = gameService.lambdaQuery().
                gt(CardGame::getStarttime, now)
                .le(CardGame::getStarttime,DateUtils.addMinutes(now,1))
                .list();
        if(cardGameList.size()==0){
            //没有查到要开始的活动
            log.info("game list scan : size = 0");
            redisUtil.del("game_task_"+now.getTime());
            return;
        }
        //2、循环遍历活动列表，挨个处理
        for (CardGame cardGame : cardGameList) {
            int cardGameId=cardGame.getId();
            //修改活动状态为已加载（status=1)
            cardGame.setStatus(1);
            //修改数据库活动状态
            gameService.lambdaUpdate().eq(CardGame::getId,cardGameId).set(CardGame::getStatus,1).update();
            long startTime = cardGame.getStarttime().getTime();
            long endTime = cardGame.getEndtime().getTime();
            long duration=endTime-startTime;
            long expireTime=(endTime-now.getTime())/1000;
            //缓存活动基本信息
            redisUtil.set(RedisKeys.INFO+cardGameId,cardGame,expireTime);
            //缓存活动的策略信息
            //查询策略信息
            List<CardGameRules> gameRules = gameRulesService.lambdaQuery()
                    .eq(CardGameRules::getGameid, cardGameId)
                    .list();
            for (CardGameRules gameRule : gameRules) {
                redisUtil.hset(RedisKeys.MAXENTER+cardGameId,gameRule.getUserlevel().toString(),gameRule.getEnterTimes(),expireTime);
                redisUtil.hset(RedisKeys.MAXGOAL+cardGameId,gameRule.getUserlevel().toString(),gameRule.getGoalTimes(),expireTime);
            }
            //缓存商品信息，生成令牌桶，
            //查询商品信息
            List<CardProductDto> products = cardProductService.getProductsByGameId(cardGameId);
            //创建令牌集合
            List<Long> tokens=new ArrayList<>();
            //缓存商品信息
            for (CardProductDto product : products) {
                int num=product.getAmount();
                for(int i=0;i<num;i++){
                    long rnd=startTime+new Random().nextInt((int) duration);
                    long token=rnd*1000+new Random().nextInt(999);
                    tokens.add(token);
                    //令牌作为key,商品作为value缓存商品
                    redisUtil.set(RedisKeys.TOKEN+cardGameId+"_"+token,product,expireTime);
                }
            }

            //排序令牌桶，存入redis
            tokens.sort(null);
            redisUtil.rightPushAll(RedisKeys.TOKENS+cardGameId,tokens);
            redisUtil.expire(RedisKeys.TOKENS+cardGameId,expireTime);
        }
        redisUtil.del("game_task_"+now.getTime());

    }
}
